package com.firmboy.search.netty.NIO;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class MyNIOServer {
	//通道管理器  
    private Selector selector;
	
	
	public static void main(String[] args) throws IOException {
		MyNIOServer nioServer = new MyNIOServer();
		nioServer.initServer(8000);
		nioServer.listen();
	}

	private void listen() throws IOException {
		System.out.println("server start");
		while(true){
			selector.select();
			
			if(selector.selectedKeys().isEmpty()){
				return;
			}
			//监听到了事件发生，返回发生的所有事件的Key（这个key是在通道注册的时候和通道绑定的
			Iterator<SelectionKey> it = selector.selectedKeys().iterator();
			
			while(it.hasNext()){
				SelectionKey key = it.next();
				
				//获取到这个key之后第一件事就是将它在当前的选中set中移除
				it.remove();
				if(key.isAcceptable()){
					//通过这个key的channel方法放回的通道包含两种，可能是服务端监听套接字或者io套接字
					ServerSocketChannel serverChannel = (ServerSocketChannel)key.channel();
					
					//获取到套接字连接
					SocketChannel accept = serverChannel.accept();
					//设置为非阻塞的
					accept.configureBlocking(false);
					
					//注册这个通道的读事件
					accept.register(selector, SelectionKey.OP_READ);
					
					
				}else if(key.isReadable()){
					SocketChannel channel = (SocketChannel)key.channel();
					ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
					
					int read = channel.read(byteBuffer);
					if(read>0){
						String string = new String(byteBuffer.array());
						
						System.out.println("receive msg:"+string);
						
						channel.write(ByteBuffer.wrap("Success".getBytes()));
					}else{
						System.out.println("channel end");
						key.cancel();
					}
				}
			}
		}
		
	}

	private void read(SelectionKey key) throws IOException {
			}

	/**
	 * 初始化server
	 * @param port
	 * @throws IOException 
	 */
	private void initServer(int port) throws IOException {
		//初始化selector
		selector = Selector.open();
		
		//获取一个socketChannel监听端口
		ServerSocketChannel socketChannel = ServerSocketChannel.open();
		
		//设置为非阻塞的
		socketChannel.configureBlocking(false);
		
		//绑定监听端口
		socketChannel.bind(new InetSocketAddress(port));
		
		//将服务端监听事件注册到多路复用器上
		
		socketChannel.register(selector, SelectionKey.OP_ACCEPT);
	}
}
